package com.swak.rpc.core;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import com.swak.rpc.Invocation;
import com.swak.rpc.Invoker;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class RpcInvocation implements Invocation, Serializable {
	private static final long serialVersionUID = 1L;
	private String protocolServiceKey;
	private String methodName;
	private String serviceName;
	private String parameterTypesDesc;
	private String[] compatibleParamSignatures;
	private Object[] arguments;
	private Map<String, Object> attachments;
	private Map<Object, Object> attributes = new HashMap<>();

	private transient Invoker<?> invoker;
	private transient Class<?> returnType;
	private transient Type[] returnTypes;
	private transient Class<?>[] parameterTypes;

	public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments) {
		this(method, serviceName, protocolServiceKey, arguments, null, null);
	}

	public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments,
			Map<String, Object> attachment, Map<Object, Object> attributes) {
		this(method.getName(), serviceName, protocolServiceKey, method.getParameterTypes(), arguments, attachment, null,
				attributes);
		this.returnType = method.getReturnType();
	}

	public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes,
			Object[] arguments) {
		this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, null, null, null);
	}

	public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes,
			Object[] arguments, Map<String, Object> attachments) {
		this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, null, null);
	}

	public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes,
			Object[] arguments, Map<String, Object> attachments, Invoker<?> invoker, Map<Object, Object> attributes) {
		this.methodName = methodName;
		this.serviceName = serviceName;
		this.protocolServiceKey = protocolServiceKey;
		this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
		this.arguments = arguments == null ? new Object[0] : arguments;
		this.attachments = attachments == null ? new HashMap<>() : attachments;
		this.attributes = attributes == null ? new HashMap<>() : attributes;
		this.invoker = invoker;
	}
}
